﻿/*
 * Netkill
 * 
 * Copyright © 2012 John Granström. All Rights Reserved.
 * 
 * This software is released under the terms and conditions of the BSD license. See 'license.txt' for details.'
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Management;
using System.Diagnostics;
using System.Windows.Forms;

namespace Netkill
{
    public class Processor
    {
        List<Process> criticalProcsRunning = new List<Process>();
        ManagementEventWatcher watcher;
        Action firstCriticalIn;
        Action lastCriticalOut;

        public Processor(Action firstCriticalIn, Action lastCriticalOut)
        {
            this.firstCriticalIn = firstCriticalIn;
            this.lastCriticalOut = lastCriticalOut;
        }

        public void StopMon()
        {
            if (watcher != null)
            {
                watcher.Stop();
                watcher.Dispose();
            }
        }

        public bool StartMon(string monString)
        {
            try
            {
                WqlEventQuery q = new WqlEventQuery();
                q.EventClassName = "Win32_ProcessStartTrace";
                q.Condition = CreateQueryFromMonString(monString);
                watcher = new ManagementEventWatcher(q);
                watcher.EventArrived += new EventArrivedEventHandler(ProcStartEventArrived);

                watcher.Start();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool RestartMon(string monString)
        {
            StopMon();
            return StartMon(monString);
        }

        private string CreateQueryFromMonString(string monString)
        {
            string[] procs = monString.Split(',');

            StringBuilder query = new StringBuilder();
            if (procs.Length > 0)
                query.Append(string.Format("ProcessName='{0}'", procs[0]));

            for (int i = 1; i < procs.Length; i++)
            {
                if (procs[i].Length > 0)
                    query.Append(string.Format(" OR ProcessName='{0}'", procs[i]));
            }

            return query.ToString();
        }

        private void ProcStartEventArrived(object sender, EventArrivedEventArgs e)
        {
            Process p = Process.GetProcessById(int.Parse(e.NewEvent.Properties["ProcessID"].Value.ToString()));
            p.EnableRaisingEvents = true;
            p.Exited += p_Exited;
            criticalProcsRunning.Add(p);

            if (criticalProcsRunning.Count == 1)
                firstCriticalIn();
        }

        void p_Exited(object sender, EventArgs e)
        {
            criticalProcsRunning.Remove((Process)sender);

            if (criticalProcsRunning.Count == 0)
                lastCriticalOut();
        }

        // Must be called at end of execution
        public void Stop()
        {
            StopMon();
        }
    }
}
